/*
 * SIT_P.h : private datatypes and prototypes that should not be used directly
 * by user.
 *
 * Written by T.Pierron, Feb 27, 2006.
 */

#ifndef	SITLIB_P_H
#define	SITLIB_P_H

#include <time.h>
#include "platform.h"
#include "SIT.h"

/* Global variables initialized in WinMain(). Not modified afterwards */
extern APTR   instance;
extern int    cmd_show, exiting;
extern Bool   has_syslink, has_theme;
extern Bool   verbose;
extern LPWSTR sit_class;
extern DWORD  win32vers;

#define VER_WIN2000    0x0500
#define VER_WINXP      0x0501
#define VER_WINVISTA   0x0600
#define VER_WIN7       0x0601
#define VER_WIN8       0x0602

/* External class for heritage */
typedef struct TagList_t           TagList;
typedef struct SIT_Dialog_t *      SIT_Dialog;
typedef struct SIT_App_t *         SIT_App;
typedef struct SIT_Label_t *       SIT_Label;
typedef struct SIT_ListBox_t *     SIT_ListBox;
typedef struct SIT_PushButton_t *  SIT_PushButton;
typedef struct SIT_EditBox_t *     SIT_EditBox;
typedef struct SIT_Canvas_t *      SIT_Canvas;
typedef struct SIT_ScrollBar_t *   SIT_ScrollBar;
typedef struct SIT_Slider_t *      SIT_Slider;
typedef struct SIT_Progress_t *    SIT_Progress;
typedef struct SIT_ComboBox_t *    SIT_ComboBox;
typedef struct SIT_DateTime_t *    SIT_DateTime;
typedef struct SIT_Tab_t *         SIT_Tab;
typedef struct SIT_Splitter_t *    SIT_Splitter;
typedef struct SIT_ToolBar_t *     SIT_ToolBar;
typedef struct SIT_Tooltip_t *     SIT_Tooltip;
typedef struct SIT_Status_t *      SIT_Status;
typedef struct SIT_FileDialog_t *  SIT_FileDialog;
typedef struct SIT_ColorDialog_t * SIT_ColorDialog;
typedef struct SIT_FontDialog_t *  SIT_FontDialog;
typedef struct SIT_FolderSel_t *   SIT_FolderSel;
typedef struct SIT_Callback_t *    SIT_Callback;
typedef struct SIT_Attach_t        SIT_Attach;
typedef struct SIT_Widget_t        SIT_Widget_t;
typedef struct SIT_CBRow_t *       SIT_CBRow;
typedef struct SIT_Timer_t *       SIT_Timer;
typedef struct SIT_MenuIcon_t *    SIT_MenuIcon;
typedef union  SIT_Variant_t       SIT_Variant;
typedef struct ClipHGlobal_t *     ClipHGlobal;

/* There is only one widget of this type. It has to be created by the user because of custom parameters */
extern SIT_App app;

struct SIT_Attach_t
{
	ULONG sa_Arg;
	int   sa_Type;
	int   sa_Offset;
};

/* Base class for all widgets */
struct SIT_Widget_t
{
	ListNode     sw_Node;
	SIT_Widget   sw_Parent;
	STRPTR       sw_Title;
	LPWSTR       sw_Name;
	SIT_TYPE     sw_Type;
	ListHead     sw_Children;
	ListHead     sw_Callbacks;
	int          sw_EvtFlags;
	ListNode     sw_Max;
	SIZE         sw_OptimalBox, sw_CurrentBox, sw_MinBox;
	SIZE         sw_ChildBox;
	Rect         sw_Box, sw_Fixed;    /* Desired pos (actual in sw_Box) */
	TagList *    sw_Class;
	HWND         sw_Handle, sw_Chain;
	HFONT        sw_Font;
	WNDPROC      sw_SuperProc;
	COLORREF     sw_Fg;
	COLORREF     sw_Bg;
	HBRUSH       sw_BgBrush;          /* Custom background color */
	STRPTR       sw_BuddyText;
	STRPTR       sw_ToolTip;
	SIT_Widget   sw_ToolTipH;
	APTR         sw_GC;
	Bool         sw_Visible;
	Bool         sw_Enabled;
	int          sw_ResizePolicy;
	int          sw_ButtonCapture;
	int          sw_TabOrder;
	HCURSOR      sw_Cursor;
	int          sw_Flags;
	int          sw_Margins[4];       /* Left, Top, Right, Bottom */
	void *       sw_UserData;
	SIT_Attach   sw_Attachment[4];    /* Left, Top, Right, Bottom */
	SIT_CallProc sw_OptimalWidth;
	SIT_CallProc sw_SetValue;
	SIT_CallProc sw_PostProcess;
	SIT_CallProc sw_Finalize;
	SIT_CallProc sw_Manage;
};

struct SIT_Callback_t
{
	ListNode     sc_Node;
	SIT_CallProc sc_CB;
	APTR         sc_UserData;
	int          sc_Event;
};

struct SIT_Dialog_t
{
	SIT_Widget_t super;
	SIT_Widget   sd_Status;  /* Can only have one */
	SIT_Widget   sd_Tooltip; /* Only one at a time */
	int          sd_ToolTimerID;
	APTR         sd_AlphaShape;
	HMENU        sd_MenuBar;
	HACCEL       sd_Accel;
	HWND         sd_Modal;
	HWND         sd_Capture;
	APTR         sd_MenuStruct;
	SIZE         sd_MinSize;
	SIZE         sd_MaxSize;
	int          sd_Type;
	int          sd_State;
	int          sd_CustomStyles;
	int          sd_Styles;
	int          sd_ExStyles;
	int          sd_ScrollWheel;
	HWND         sd_WheelWnd;
	HICON        sd_Icon;
	ListHead     sd_SyncTB;
	SIT_MenuIcon sd_MenuIcons;
	int          sd_MICount;
};

struct SIT_MenuIcon_t
{
	HIMAGELIST imgList, imgDisa;
	uint16_t   imgId, menuId;
	uint16_t   width, height;
	Image      img;
};

typedef struct SharedSeg_t *    SharedSeg;

struct SharedSeg_t
{
	int  threadid;
	int  argc;
	TEXT argv[0x800-2*sizeof(int)];
};

struct SIT_App_t
{
	SIT_Widget_t super;
	Bool         sa_UniqueApp, sa_Ret;
	HANDLE       sa_Mapping;
	SharedSeg    sa_Data;
	LocaleInfo   sa_Locale;
	int          sa_ClipSeq;
	STRPTR       sa_CurrentDir;
	STRPTR     * sa_Formats; /* Clipboard */
	ListHead     sa_Timers; /* SIT_Timer */
};

struct SIT_Timer_t
{
	ListNode     node;
	SIT_Widget   w;
	SIT_CallProc cb;
	APTR         ud;
	int          timerid;
};

struct SIT_Label_t
{
	SIT_Widget_t super;
	Bool         sl_SysLink;
	int          sl_Center;
	int          sl_CenterVert;
	int          sl_Overflow;
	int          sl_Frame;
};

struct SIT_ListBox_t
{
	SIT_Widget_t super;
	int          sl_Flags;
	int          sl_ColumnCount;
	STRPTR       sl_ColumnNames;
	STRPTR       sl_ColumnWidths;
	STRPTR       sl_ColumnAlign;
	int *        sl_CWidths;
	int          sl_NCWidth;
	int          sl_DivTrack;
	int          sl_CancelEvt;
	int          sl_PrevSort;
	int          sl_SortColumn;
	int          sl_ViewMode;
	int          sl_SelIndex;
	int          sl_CurRow;
	STRPTR       sl_CurItem;
	STRPTR       sl_BgPattern;
	int          sl_BgRepeat;
	POINT        sl_BgPos;
	HIMAGELIST   sl_ImgList;
	APTR         gc;
	COLORREF     fg, bg;
};

struct SIT_PushButton_t
{
	SIT_Widget_t super;
	int          sb_Type;
	int          sb_State;
	int          sb_Group;
	int          sb_IconMargin;
	int          sb_IconOrient;
	int          sb_AlignText;
	int *        sb_CurValue;
	int          sb_RadioID;
	SIZE         sb_IconSize;
	STRPTR       sb_IconPath;
	APTR         sb_IconImage;
	APTR         sb_Icon; /* ImageList */
};

struct SIT_EditBox_t
{
	SIT_Widget_t super;
	int          se_Flags;
	int          se_EditType;
	Bool         se_ReadOnly;
	Bool         se_CancelEvent;
	Bool         se_TempEdit;
	int          se_StartSel, se_EndSel;
	int          se_MinValue;
	int          se_MaxValue;
	int          se_BufLen;
	int          se_HotKey;
	int *        se_CurValue;
	STRPTR       se_CueBanner;
	HANDLE       se_UpDown;
	SIT_Widget   se_BuddyTB;
	WNDPROC      se_EditProc;
};

struct SIT_Canvas_t
{
	SIT_Widget_t super;
	int          sc_CaretState;
	Bool         sc_CaretCreated;
	Bool         sc_AutoFocus, sc_HasFocus, sc_UserBgClear, sc_FullErase;
	int          sc_CaretW, sc_CaretH;
	int          sc_CaretX, sc_CaretY;
	int          sc_Frame;
	SIZE         sc_Box;
};

struct SIT_ScrollBar_t
{
	SIT_Widget_t super;
	int          sb_LineHeight;
	Bool         sb_IsHoriz;
	Bool         sb_IsDragged;
	SCROLLINFO   sb_Info;
};

struct SIT_Slider_t
{
	SIT_Widget_t super;
	int          tb_MinValue;
	int          tb_MaxValue;
	int          tb_PageSize;
	int          tb_SliderPos;
	int          tb_Styles;
	int          tb_TickFreq;
	int          tb_Mask;
	int          tb_ThumbWidth;
	Bool         tb_IsHoriz;
	SIT_Widget   tb_Buddy;
};

struct SIT_Progress_t
{
	SIT_Widget_t super;
	int          pb_MinValue;
	int          pb_MaxValue;
	int          pb_ProgressPos;
	int          pb_Mask;
	Bool         pb_IsHoriz;
	LPWSTR       pb_TextCache;
	int          pb_PosCache;
};

struct SIT_CBRow_t
{
	STRPTR entry;
	APTR   tag;
};

struct SIT_ComboBox_t
{
	SIT_Widget_t super;
	SIT_CBRow    sc_RowTags;
	STRPTR       sc_Values, sc_InitValues;
	Bool         sc_AutoComplete;
	int          sc_Count, sc_Items;
	int          sc_SelIndex;
	int          sc_ReadOnly;
	int          sc_Flags;
	int          sc_ItemHeight;
	int          sc_MinHeight;
	HWND         sc_Edit;
	WNDPROC      sc_EditProc;
};

struct SIT_DateTime_t
{
	SIT_Widget_t super;
	int          sd_DateFormat;
	STRPTR       sd_DateTimeFmt;
	struct tm    sd_CurDate;
	Bool         sd_SetDate;
};

struct SIT_Tab_t
{
	SIT_Widget_t super;
	STRPTR       st_TabStr;
	ListHead     st_Items;      // SITV_TabInvisible only
	int          st_TabStyle;
	int          st_NbTab;
	int          st_CurTab;
	int          st_TabIndex;
	int          st_AutoHide;
	int          st_ClipChld;
	int          st_LastImgId;
	RECT         st_TabMargins;
	HIMAGELIST   st_Icons;
};

struct SIT_Splitter_t
{
	SIT_Widget_t super;
	int          sp_Style;
	Bool         sp_Horiz;
	Bool         sp_LiveResize;
	int          sp_MinSizeLeft;
	int          sp_MinSizeRight;
	POINT        sp_Init;
	int          sp_CurPos;
	HDC          sp_WndHDC;
	HBRUSH       sp_Bg;
};

struct SIT_ToolBar_t
{
	SIT_Widget_t     super;
	int              tb_Style;
	int              tb_DefButtons;
	Bool             tb_LargeIcons;
	Bool             tb_SyncWithMenu;
	Bool             tb_HasCustCtrl;
	uint8_t          tb_Index[6];
	HWND             tb_Handle;
	SIT_ToolButton * tb_Buttons;
	HIMAGELIST       tb_ImgList;
	HIMAGELIST       tb_Disabled;
	ListHead         tb_Tips;
	ListNode         tb_Sync;
};

#define TOOLBAR(node)   ((SIT_ToolBar)((STRPTR)node - offsetof(struct SIT_ToolBar_t, tb_Sync)))

#define	TB_CUSTOMCTRL     32000

struct SIT_Tooltip_t
{
	SIT_Widget_t super;
	SIT_Widget   tt_Parent;
	int          tt_Styles;
	int          tt_SubRect;
	STRPTR       tt_Header;
	int          tt_Icon;
	int          tt_DisplayTime;
};

struct SIT_Status_t
{
	SIT_Widget_t super;
	int          st_Styles;
	STRPTR       st_LabelSize;
	int          st_StatusPart;
};

struct SIT_FileDialog_t
{
	SIT_Widget_t super;
	STRPTR       sf_Filters;
	int          sf_SelFilter;
	STRPTR       sf_InitPath;
	int          sf_Flags;
	STRPTR *     sf_SaveState;
	int          sf_NbSelect;
	STRPTR       sf_FilePtr;
	WCHAR        sf_FileName[1024];
	OPENFILENAME ofn;
};

struct SIT_ColorDialog_t
{
	SIT_Widget_t super;
	LONG         sc_Color;
	LONG         sc_OldColor;
	CHOOSECOLOR  cc;
};

struct SIT_FontDialog_t
{
	SIT_Widget_t super;
	Bool         sf_FixedFont;
	STRPTR       sf_SelFont;
	CHOOSEFONT   cf;
	LOGFONT      lf;
};

struct SIT_FolderSel_t
{
	SIT_Widget_t super;
	STRPTR       sf_InitPath;
	IMalloc *    inf;
	WCHAR        path[MAX_PATH];
	BROWSEINFO   bi;
};

union SIT_Variant_t
{
	int    integer;
	long   longInt;
	double real;
	void * pointer;
	BOOL   boolean;
	STRPTR string;
};

enum /* Bitfield for sw_Flags */
{
	SITF_GeometrySet     = 0x1,
	SITF_GeometryChanged = 0x2,
	SITF_HasCustFg       = 0x4,        // sw_Fg is valid
	SITF_HasCustBg       = 0x8,        // sw_Bg is valid
	SITF_FixedX          = 0x10,       // Inform layout manager
	SITF_FixedY          = 0x20,
	SITF_FixedWidth      = 0x40,
	SITF_FixedHeight     = 0x80,
	SITF_Style1Changed   = 0x100,      // Stock flags for handling properties modification
	SITF_Style2Changed   = 0x200,
	SITF_StylesChanged   = 0x300,
	SITF_IsLocked        = 0x400,      // An event has a pending process
	SITF_BeingDestroyed  = 0x800,      // User ask to delete that control
	SITF_CanResizeW      = 0x1000,     // At least one control has a right attach on the form
	SITF_CanResizeH      = 0x2000,     // A control has a bottom attach on the form
	SITF_HandleEraseBg   = 0x4000,     // Ask to redirect WM_ERASEBACKGROUND
	SITF_KeepDiagSize    = 0x8000,     // Width/height changed on dialog - keep it
	SITF_TopLevel        = 0x10000,    // Top level window, not part of children layout
	SITF_Internal        = 0x20000,
	SITF_GeomNotified    = 0x40000,    // Geometry modification message has been posted
	SITF_NCMargins       = 0x80000,    // Margins are handled by non-client area
	SITF_AutoHeight      = 0x100000,   // Need to set control's size before triggering OnResize
	SITF_RestoreSize     = 0x200000,
	SITF_PostProcess     = 0x400000,   // Process SIT_HandleEraseBg
	SITF_ReflowW         = 0x800000,
	SITF_ReflowH         = 0x1000000,
	SITF_CustomCursor    = 0x2000000,
	SITF_ListEvt         = 0x80000000
};

enum /* Private tags */
{
	SIT_SuperClass = 0x1000,
	SIT_EditClass
};

enum /* Private geometry attachment */
{
	SITV_AttachFixed = 7
};

enum /* Private event handler */
{
	SITE_OnNCPaint    = 31,
	SITE_OnNCCalcSize = 30
};

struct TagList_t
{
	int    tl_TagID;
	STRPTR tl_TagName;
	int    tl_Flags;
	int    tl_Type;
	ULONG  tl_Arg;
};

struct ClipHGlobal_t
{
	ListNode node;
	HGLOBAL  hglob;
	APTR     mem;
};

extern TagList WidgetClass[];

enum /* bitfield for tl_Flags */
{
	___ = 0x0,    // Internal usage
	__G = 0x1,    // Read only
	_S_ = 0x2,    // Write only
	_SG = 0x3,    // No side effect property
	C__ = 0x4,    // Create only
	CSG = 0x7     // Setting property will imply visual changes (geometry)
};

/* For tl_Arg */
#define	OFFSET(ptrType, fieldName) ((ULONG) &((ptrType)0L)->fieldName)
#define	ARRAY(nb)                  ((nb) << 4)

/* Create an ID for CreateWindow() */
#define	MAKE_ID(widget)            ((widget)->sw_Parent->sw_Children.lh_Count + 10)

/* Check if an event is defined for given control */
#define	HAS_EVT(w, type)           ((w)->sw_EvtFlags & (1 << (type)))
#define HAS_1OF2EVT(w, e1, e2)     ((w)->sw_EvtFlags & ((1 << (e1)) | (1 << (e2))))
#define	SET_EVT(w, type)           if (type < 32) w->sw_EvtFlags |= 1 << type
#define	HAS_TAB(w)                 (w->sw_TabOrder & 0xffff)

/* Abbreviation of up to 4 tags */
#define	ABBR(a, b, c, d)           (a | (b << 8) | (c << 16) | (d << 24))

/* Private tags */
#define	SIT_BuddyCtrl  (SIT_TagPrivate-1)
#define	SIT_BuddyText  (SIT_TagPrivate-2)


enum /* Types for ParseTags */
{
	SIT_INT,
	SIT_LONG,
	SIT_BOOL,
	SIT_STR,
	SIT_DBL,
	SIT_PTR,
	SIT_CTRL,
	SIT_ABBR
};


/* Internal usage function */
BOOL   SIT_CreateApp(SIT_Widget, va_list);
BOOL   SIT_CreateDialog(SIT_Widget, va_list);
BOOL   SIT_CreateLabel(SIT_Widget, va_list);
BOOL   SIT_CreateButton(SIT_Widget, va_list);
BOOL   SIT_CreateEditBox(SIT_Widget, va_list);
BOOL   SIT_CreateFrame(SIT_Widget, va_list);
BOOL   SIT_CreateListBox(SIT_Widget, va_list);
BOOL   SIT_CreateCanvas(SIT_Widget, va_list);
BOOL   SIT_CreateScrollBar(SIT_Widget, va_list);
BOOL   SIT_CreateSlider(SIT_Widget, va_list);
BOOL   SIT_CreateProgress(SIT_Widget, va_list);
BOOL   SIT_CreateComboBox(SIT_Widget, va_list);
BOOL   SIT_CreateDateTime(SIT_Widget, va_list);
BOOL   SIT_CreateTab(SIT_Widget, va_list);
BOOL   SIT_CreateSplitter(SIT_Widget, va_list);
BOOL   SIT_CreateToolbar(SIT_Widget, va_list);
BOOL   SIT_CreateTooltip(SIT_Widget, va_list);
BOOL   SIT_CreateStatus(SIT_Widget, va_list);
BOOL   SIT_CreateFileDialog(SIT_Widget, va_list);
BOOL   SIT_CreateColorDialog(SIT_Widget, va_list);
BOOL   SIT_CreateFolderDialog(SIT_Widget, va_list);
BOOL   SIT_CreateFontDialog(SIT_Widget, va_list);
BOOL   SIT_RegisterClass(SIT_Widget, LPWSTR cls, int flags, LPWSTR arrow, APTR icon);
void   SIT_ParseTags(SIT_Widget, va_list, TagList *);
int    SIT_ApplyCallback(SIT_Widget, APTR cd, int type);
void   SIT_SetDefaultFont(SIT_Widget);
BOOL   SIT_LayoutWidgets(SIT_Widget, int adjust);
HWND   SIT_GetContainer(SIT_Widget);
int    SIT_SetWidgetValue(SIT_Widget w, APTR cd, APTR ud);
void   SIT_UncheckRadio(SIT_Widget);
void   SIT_SyncCBValue(SIT_PushButton);
Bool   SIT_EditGetText(SIT_EditBox);
void   SIT_SetTitle(SIT_Widget);
APTR   SIT_CreateMenu(SIT_Widget, HMENU, SIT_MenuStruct *, int pos);
int    SIT_AddMenuIcon(SIT_Widget, int menuid, HIMAGELIST list, HIMAGELIST disa, int id, Image img);
void   SIT_DelMenuIcon(SIT_Widget, int id);
void   SIT_DelMenuIconHList(SIT_Widget, HIMAGELIST list, int id);
void   SIT_SetStatusPart(SIT_Widget);
void   SIT_HandleAutoMenu(SIT_Widget, int menuid);
int    SIT_ComboBoxItemHeight(SIT_Widget);
void   SIT_SetComboListWithTags(SIT_ComboBox);
void   SIT_TitleHeight(SIT_Widget, LPWSTR str, SIZE *);
void   SIT_AdjustWindowRect(SIT_Dialog, RECT * rect, RECT * adj_lt);
void   SIT_DestroyWidget(SIT_Widget);
void   SIT_DestroyChildren(SIT_Widget);
void   SIT_MoveWidgets(SIT_Widget);
LPWSTR SIT_ToolbarGetTip(SIT_Widget, int id);
void   SIT_ToolbarSyncWithMenu(SIT_Widget, int id);
void   SIT_UpdateLayeredWindow(SIT_Widget);
Bool   SIT_ReassignAttachments(SIT_Widget);
void   SIT_SyncDate(SIT_Widget, LPSYSTEMTIME sys);
void   SIT_CreateBuddyLabel(SIT_Widget buddy, STRPTR text, SIT_Widget * max);
APTR   SIT_FindControl(SIT_Widget parent, STRPTR utf8, int len, Bool recursive);
int    SIT_HandleListCustomDraw(SIT_Widget, LPNMLVCUSTOMDRAW);
APTR   SIT_CreateTip(SIT_Widget parent, STRPTR fmt); // Will free 'fmt'
Bool   IsVisible(SIT_Widget);
STRPTR SIT_FormatName(int type);
STRPTR * SIT_GetClipboardFormats(void);
void   SIT_InitiateReflow(SIT_Widget);
void   SIT2Accel(SIT_MenuStruct *, LPACCEL);
HICON  SIT_IconFromBitmap(Image);
HCURSOR SIT_ImageToCursor(Image);
HBITMAP SIT_GrayedImageAlpha(Image, DATA8 dest);
void    ApplyMask(DATA8 dest, int w, int h, DATA8 src, int x, int y, ULONG color);

LRESULT CALLBACK SIT_SubClassHandler(HWND, UINT, WPARAM, LPARAM);

extern int sysColorsWin32[];
extern uint8_t sit2vk[];

enum /* Values for 'adjust' parameter of SIT_LayoutWidgets() */
{
	KeepDialogSize,
	FitUsingOptimalBox,
	FitUsingCurrentBox,
	FitUsingInitialBox
};

#define	SNEXT(node, field)      node = (APTR) ((node)->field.ln_Next)

#define	WM_ONUSER          WM_APP
#define	WM_COMBOCHG        (WM_APP+1)
#define	WM_GEOMETRY        (WM_APP+2)
#define	WM_NEWINSTANCE     (WM_APP+3)
#define	WM_DELAYDESTROY    (WM_APP+4)

#ifndef	ABS
#define	ABS(x)     ((x) < 0 ? - (x) : (x))
#endif

/* Has to be a macro because of alloca */
#define UTF8ToUTF16(utf8, utf16) \
{ \
	int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0); \
\
	utf16 = alloca(len * sizeof *utf16); \
\
	MultiByteToWideChar(CP_UTF8, 0, utf8, -1, (LPWSTR) utf16, len); \
}

#define	utf16len(utf8) \
	MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0)

#endif
